﻿using System;
using System.Text.RegularExpressions;
using InterPC.SPF.SPFMechanisms;

/// 
/// Contains SPF Modifier class
///

namespace InterPC.SPF {

    /// <summary>
    /// SPF modifier base class
    /// </summary>
    public class SPFModifierTerm : SPFTerm {

        private SPFModifierType _ModifierType;
        /// <summary>
        /// Returns the type of the modifier
        /// </summary>
        public SPFModifierType ModifierType {
            get { return _ModifierType; }
        }
        private string _ModifierString;
        /// <summary>
        /// Return the raw string of the modifier definition
        /// </summary>
        public string ModifierString {
            get { return _ModifierString; }
        }
        private string _Arg;
        /// <summary>
        /// Return the argument of the modifier if any
        /// </summary>
        public string Arg {
            get { return _Arg; }
        }

        /// <summary>
        /// Main constructor
        /// </summary>
        public SPFModifierTerm() : base(SPFTermType.Modifier) { }

        /// <summary>
        /// Parse a string to a modifier term object
        /// Throw an exception if the format is incorrect
        /// </summary>
        /// <param name="datas"></param>
        /// <returns></returns>
        public new static SPFModifierTerm Parse(string datas) {
            // Base format validation
            Regex ModReg = new Regex(@"^(?<modifier>[^=:/]+)=(?<argument>.+)$", RegexOptions.IgnoreCase);
            Match M = ModReg.Match(datas);
            if (!M.Success)
                throw new FormatException(string.Format("Modifier format is incorrect ({0})", datas));

            // Try to get the SPFModifierType from the string
            SPFModifierType MType = SPFModifierType.Unknown;
            try {
                MType = (SPFModifierType)Enum.Parse(typeof(SPFModifierType), M.Groups["modifier"].Value, true);
            }
            catch { }

            // Unkown modifier must begin with alpha
            if (MType == SPFModifierType.Unknown && !Regex.IsMatch(M.Groups["modifier"].Value, "^[a-zA-Z]"))
                throw new FormatException("Unkown modifier must begin with alpha");

            // If exp arg is a mechanism term raise syntax error
            if (MType == SPFModifierType.Exp) {
                SPFMechanismTerm T = null;
                try {
                    T = SPFMechanismTerm.Parse(M.Groups["argument"].Value);
                }
                catch { }
                if (T != null)
                    throw new FormatException("Syntax error");
            }

            // Build the new object
            string MModString = M.Groups["modifier"].Value;
            string MArg = M.Groups["argument"].Value;

            // Unkown modifier must have valid macro syntaxe
            if (MType == SPFModifierType.Unknown && Regex.IsMatch(MArg, "%[^%]")) {
                if (SPFChecker.Reg_MacroSyntaxError.IsMatch(MArg) || !SPFChecker.Reg_MacroRegExStrict.IsMatch(MArg)) 
                    throw new FormatException("Syntax error in macro (unknown modifier)");
            }

            return new SPFModifierTerm() { _Arg = MArg, _ModifierType = MType, _ModifierString = MModString };
        }

        // Return the normalized string representation of the modifier
        public override string ToString() {
            return string.Format("{0}={1}", _ModifierString, _Arg);
        }
    }

}
